#if PocketPC || !Framework20
using System;
using System.Threading;

namespace GeoFramework.IO
{
	/// <summary>Represents a base class for designing safe unmanaged handle managers.</summary>
	/// <remarks>
	/// 	<para>This class is provided as a way to safely manage unmanaged resources, namely
	///     handles used during platform invoke calls. When a new file handle is created, such
	///     as with the <strong>CreateFile</strong> API, a this class will ensure that the
	///     <strong>CloseHandle</strong> method is always called to release the handle. If
	///     necessary, the handle is released during the finalizer.</para>
	/// 	<para>Safe handles provide a clean way to manage handles and should be used in
	///     every situation where a platform invoke requires a handle. Using this class is also
	///     preferable because it can remove the need for a parent class to implement
	///     <strong>IDisposable</strong>, which simplifies classes.</para>
	/// 	<para>This class is used primarily by the <strong>SerialStream</strong> and
	///     <strong>BluetoothStream</strong> classes to perform platform invoke calls within a
	///     safe context.</para>
	/// </remarks>
	public abstract class SafeHandle
	{
		private bool pIsClosed;
		private bool pIsOwner;	

		/// <summary>Returns the handle to an unmanaged resource.</summary>
		protected IntPtr handle;

		protected SafeHandle(IntPtr invalidHandleValue, bool ownsHandle)
		{
			pIsOwner = ownsHandle;

#if !PocketPC
            // No need to finalize YET
			GC.SuppressFinalize(this);
#endif
		}

		~SafeHandle()
		{
			Close();
		}

		protected void SetHandle(IntPtr handle)
		{
			// Do we already have a handle?
			if (!IsInvalid && !pIsClosed && pIsOwner)
				// Yes.  Release it
				ReleaseHandle();

			// And set the new value
			this.handle = handle;

#if !PocketPC
            // We need to finalize now
			GC.ReRegisterForFinalize(this);
#endif

        }

		/// <summary>Closes the unmanaged resource associated with the handle.</summary>
		public void Close()
		{
            // No need to finalize
			GC.SuppressFinalize(this);

			if (!IsInvalid && !pIsClosed && pIsOwner)
			{
				pIsClosed = ReleaseHandle();
			}
		}

		/// <summary>Indicates if the handle has been successfully closed.</summary>
		public bool IsClosed
		{
			get
			{
				if (IsInvalid)
					return true;
				return pIsClosed;
			}
		}

		/// <summary>Indicates if the handle is valid.</summary>
		public abstract bool IsInvalid { get; }
		protected abstract bool ReleaseHandle();

		/// <summary>Returns the handle as an <strong>IntPtr</strong>.</summary>
		public IntPtr DangerousGetHandle()
		{
			return handle;
		}
	}
}
#endif
